import type { App } from 'vue';
import {
  type RouterHistory,
  createMemoryHistory,
  createRouter,
  createWebHashHistory,
  createWebHistory
} from 'vue-router';
import { createBuiltinVueRoutes } from './routes/builtin';
import { createRouterGuard } from './guard';
import { layouts, views } from './elegant/imports';
import { getRoutePath } from './elegant/transform';

const { VITE_ROUTER_HISTORY_MODE = 'history', VITE_BASE_URL } = import.meta.env;

const historyCreatorMap: Record<Env.RouterHistoryMode, (base?: string) => RouterHistory> = {
  hash: createWebHashHistory,
  history: createWebHistory,
  memory: createMemoryHistory
};

export const router = createRouter({
  history: historyCreatorMap[VITE_ROUTER_HISTORY_MODE](VITE_BASE_URL),
  routes: createBuiltinVueRoutes()
});

/** Setup Vue Router */
export async function setupRouter(app: App) {
  app.use(router);
  createRouterGuard(router);
  await router.isReady();
}

/**
 * Convert backend route to vue router route
 * @param route - Backend route
 */
function convertBackendRoute(route: any) {
  // Handle component
  let component: any = null;

  if (route.component === 'Layout') {
    component = (layouts as any)['default'] || Object.values(layouts)[0];
  } else if (route.component === 'ParentView') {
    component = (layouts as any)['parentView'] || Object.values(layouts)[0];
  } else if ((views as any)[route.component]) {
    component = (views as any)[route.component];
  } else {
    // Fallback to 404 if component not found
    component = (views as any)['404'];
  }

  const vueRoute: any = {
    path: route.path?.startsWith('/') ? route.path : '/' + route.path,
    name: route.name,
    component,
    meta: route.meta || {},
    redirect: route.redirect,
  };

  // Handle children routes
  if (Array.isArray(route.children) && route.children.length > 0) {
    vueRoute.children = route.children.map(convertBackendRoute);
  }

  return vueRoute;
}

/**
 * Add dynamic routes from backend
 * @param routes - Backend routes
 */
export async function addDynamicRoutes(routes: any[]) {
  // Process all routes
  if (!routes || routes.length === 0) return;

  const vueRoutes = routes.map(route => convertBackendRoute(route));

  // Add routes to router
  vueRoutes.forEach(route => {
    try {
      router.addRoute(route);
    } catch (error) {
      console.error('Failed to add route:', route, error);
    }
  });

  // Set root redirect to the first available route
  if (vueRoutes.length > 0) {
    const firstRoute = vueRoutes[0];
    router.addRoute({
      path: '/',
      redirect: firstRoute.path
    });
  }

  // Add 404 route at the end
  router.addRoute({
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: (views as any)['404']
  });
}
